package com.snowy.framework.exception;

import com.snowy.framework.common.resp.BaseResp;
import com.snowy.framework.common.resp.BaseRespUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.binding.BindingException;
import org.mybatis.spring.MyBatisSystemException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.el.PropertyNotFoundException;
import javax.management.BadStringOperationException;
import javax.net.ssl.SSLHandshakeException;
import java.io.EOFException;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.SocketTimeoutException;
import java.security.cert.CertificateException;
import java.sql.SQLException;
import java.util.concurrent.TimeoutException;

/**
 * 异常处理器
 *
 * @Author cl
 * @Date 2019
 */
@RestControllerAdvice
@Slf4j
public class UABPExceptionHandler {

    /**
     * 处理自定义异常
     */
    @ExceptionHandler(UABPException.class)
    public BaseResp<?> handleRRException(UABPException e) {
        log.error(e.getMessage(), e);
        return BaseRespUtil.Error(e);
    }

    @ExceptionHandler(NoHandlerFoundException.class)
    public BaseResp<?> handlerNoFoundException(Exception e) {
        log.error(e.getMessage(), e);
        return BaseRespUtil.Error("404", "路径不存在，请检查路径是否正确");
    }

    @ExceptionHandler(DuplicateKeyException.class)
    public BaseResp<?> handleDuplicateKeyException(DuplicateKeyException e) {
        log.error(e.getMessage(), e);
        return BaseRespUtil.Error("1000", "数据库中已存在该记录");
    }

    // region RuntimeException

    @ExceptionHandler(ArrayIndexOutOfBoundsException.class)
    public BaseResp<?> handleArrayIndexOutOfBoundsException(ArrayIndexOutOfBoundsException e) {
        log.error(e.getMessage(), e);
        return  BaseRespUtil.Error(ExceptionENU.ArrayIndexOutOfBoundsException.getCode(),ExceptionENU.ArrayIndexOutOfBoundsException.getMsg());
    }

    @ExceptionHandler(ArithmeticException.class)
    public BaseResp<?> handleArithmeticException(ArithmeticException e) {
        log.error(e.getMessage(), e);
        return BaseRespUtil.Error(ExceptionENU.ArithmeticException.getCode(), ExceptionENU.ArithmeticException.getMsg());
    }

    @ExceptionHandler(SecurityException.class)
    public BaseResp<?> handleSecurityException(SecurityException e) {
        log.error(e.getMessage(), e);
        return BaseRespUtil.Error(ExceptionENU.SecurityException.getCode(), ExceptionENU.SecurityException.getMsg());
    }

    @ExceptionHandler(IllegalArgumentException.class)
    public BaseResp<?> handleIllegalArgumentException(IllegalArgumentException e) {
        log.error(e.getMessage(), e);
        return BaseRespUtil.Error(ExceptionENU.IllegalArgumentException.getCode(), ExceptionENU.IllegalArgumentException.getMsg());
    }

    @ExceptionHandler(ArrayStoreException.class)
    public BaseResp<?> handleArrayStoreException(ArrayStoreException e) {
        log.error(e.getMessage(), e);
        return BaseRespUtil.Error(ExceptionENU.ArrayStoreException.getCode(), ExceptionENU.ArrayStoreException.getMsg());
    }

    @ExceptionHandler(NegativeArraySizeException.class)
    public BaseResp<?> handleNegativeArraySizeException(NegativeArraySizeException e) {
        log.error(e.getMessage(), e);
        return BaseRespUtil.Error(ExceptionENU.NegativeArraySizeException.getCode(), ExceptionENU.NegativeArraySizeException.getMsg());
    }

    @ExceptionHandler(ClassCastException.class)
    public BaseResp<?> handleClassCastException(ClassCastException e) {
        log.error(e.getMessage(), e);
        return BaseRespUtil.Error(ExceptionENU.ClassCastException.getCode(), ExceptionENU.ClassCastException.getMsg());
    }

    @ExceptionHandler(NullPointerException.class)
    public BaseResp<?> handleNullPointerException(NullPointerException e) {
        log.error(e.getMessage(), e);
        return BaseRespUtil.Error(ExceptionENU.NullPointerException.getCode(), ExceptionENU.NullPointerException.getMsg());
    }

    @ExceptionHandler(NumberFormatException.class)
    public BaseResp<?> handleNumberFormatException(NumberFormatException e) {
        log.error(e.getMessage(), e);
        return BaseRespUtil.Error(ExceptionENU.NumberFormatException.getCode(), ExceptionENU.NumberFormatException.getMsg());
    }

    @ExceptionHandler(StringIndexOutOfBoundsException.class)
    public BaseResp<?> handleStringIndexOutOfBoundsException(StringIndexOutOfBoundsException e) {
        log.error(e.getMessage(), e);
        return BaseRespUtil.Error(ExceptionENU.StringIndexOutOfBoundsException.getCode(), ExceptionENU.StringIndexOutOfBoundsException.getMsg());
    }
    // endregion

    // region IOException

    @ExceptionHandler(IOException.class)
    public BaseResp<?> handleIOException(IOException e) {
        log.error(e.getMessage(), e);
        return BaseRespUtil.Error(ExceptionENU.IOException.getCode(), ExceptionENU.IOException.getMsg());
    }

    @ExceptionHandler(EOFException.class)
    public BaseResp<?> handleEOFException(EOFException e) {
        log.error(e.getMessage(), e);
        return BaseRespUtil.Error(ExceptionENU.EOFException.getCode(), ExceptionENU.EOFException.getMsg());
    }

    @ExceptionHandler(FileNotFoundException.class)
    public BaseResp<?> handleFileNotFoundException(FileNotFoundException e) {
        log.error(e.getMessage(), e);
        return BaseRespUtil.Error(ExceptionENU.FileNotFoundException.getCode(), ExceptionENU.FileNotFoundException.getMsg());
    }

//    @ExceptionHandler(LoadException.class)
//    public BaseResp<?> handleLoadException(LoadException e) {
//        log.error(e.getMessage(), e);
//        return BaseRespUtil.Error(ExceptionENU.LoadException.getCode(), ExceptionENU.LoadException.getMsg());
//    }
    // endregion

    // region 其他

    @ExceptionHandler(SQLException.class)
    public BaseResp<?> handleSQLException(SQLException e) {
        log.error(e.getMessage(), e);
        return BaseRespUtil.Error(ExceptionENU.SQLException.getCode(), ExceptionENU.SQLException.getMsg());
    }

    @ExceptionHandler(NoSuchFieldException.class)
    public BaseResp<?> handleNoSuchFieldException(NoSuchFieldException e) {
        log.error(e.getMessage(), e);
        return BaseRespUtil.Error(ExceptionENU.NoSuchFieldException.getCode(), ExceptionENU.NoSuchFieldException.getMsg());
    }

    @ExceptionHandler(NoSuchMethodException.class)
    public BaseResp<?> handleNoSuchMethodException(NoSuchMethodException e) {
        log.error(e.getMessage(), e);
        return BaseRespUtil.Error(ExceptionENU.NoSuchMethodException.getCode(), ExceptionENU.NoSuchMethodException.getMsg());
    }

    @ExceptionHandler(IllegalAccessException.class)
    public BaseResp<?> handleIllegalAccessException(IllegalAccessException e) {
        log.error(e.getMessage(), e);
        return BaseRespUtil.Error(ExceptionENU.IllegalAccessException.getCode(), ExceptionENU.IllegalAccessException.getMsg());
    }

    @ExceptionHandler(InstantiationException.class)
    public BaseResp<?> handleInstantiationException(InstantiationException e) {
        log.error(e.getMessage(), e);
        return BaseRespUtil.Error(ExceptionENU.InstantiationException.getCode(), ExceptionENU.InstantiationException.getMsg());
    }

    @ExceptionHandler(ClassNotFoundException.class)
    public BaseResp<?> handleClassNotFoundException(ClassNotFoundException e) {
        log.error(e.getMessage(), e);
        return BaseRespUtil.Error(ExceptionENU.ClassNotFoundException.getCode(), ExceptionENU.ClassNotFoundException.getMsg());
    }

    @ExceptionHandler(TimeoutException.class)
    public BaseResp<?> handleTimeoutException(TimeoutException e) {
        log.error(e.getMessage(), e);
        return BaseRespUtil.Error(ExceptionENU.TimeoutException.getCode(), ExceptionENU.TimeoutException.getMsg());
    }

    @ExceptionHandler(BadStringOperationException.class)
    public BaseResp<?> handleBadStringOperationException(BadStringOperationException e) {
        log.error(e.getMessage(), e);
        return BaseRespUtil.Error(ExceptionENU.BadStringOperationException.getCode(), ExceptionENU.BadStringOperationException.getMsg());
    }
    // endregion

    // region mybatis

    @ExceptionHandler(BindingException.class)
    public BaseResp<?> handleBindingException(BindingException e) {
        log.error(e.getMessage(), e);
        return BaseRespUtil.Error(ExceptionENU.BindingException.getCode(), ExceptionENU.BindingException.getMsg());
    }

    @ExceptionHandler(PropertyNotFoundException.class)
    public BaseResp<?> handlePropertyNotFoundException(PropertyNotFoundException e) {
        log.error(e.getMessage(), e);
        return BaseRespUtil.Error(ExceptionENU.PropertyNotFoundException.getCode(), ExceptionENU.PropertyNotFoundException.getMsg());
    }

    @ExceptionHandler(MyBatisSystemException.class)
    public BaseResp<?> handleMyBatisSystemException(MyBatisSystemException e) {
        log.error(e.getMessage(), e);
        return BaseRespUtil.Error(ExceptionENU.MyBatisSystemException.getCode(), ExceptionENU.MyBatisSystemException.getMsg());
    }
    // endregion

    // region Redis
    // endregion

    // region Http

    @ExceptionHandler(SocketTimeoutException.class)
    public BaseResp<?> handleSocketTimeoutException(SocketTimeoutException e) {
        log.error(e.getMessage(), e);
        return BaseRespUtil.Error(ExceptionENU.SocketTimeoutException.getCode(), ExceptionENU.SocketTimeoutException.getMsg());
    }

//    @ExceptionHandler(ConnectTimeoutException.class)
//    public BaseResp<?> handleMyBatisSystemException(MyBatisSystemException e) {
//        log.error(e.getMessage(), e);
//        return BaseRespUtil.Error(ExceptionENU.MyBatisSystemException.getCode(), ExceptionENU.MyBatisSystemException.getMsg());
//    }

    @ExceptionHandler(SSLHandshakeException.class)
    public BaseResp<?> handleSSLHandshakeException(SSLHandshakeException e) {
        log.error(e.getMessage(), e);
        return BaseRespUtil.Error(ExceptionENU.SSLHandshakeException.getCode(), ExceptionENU.SSLHandshakeException.getMsg());
    }

    @ExceptionHandler(CertificateException.class)
    public BaseResp<?> handleCertificateException(CertificateException e) {
        log.error(e.getMessage(), e);
        return BaseRespUtil.Error(ExceptionENU.CertificateException.getCode(), ExceptionENU.CertificateException.getMsg());
    }

    @ExceptionHandler(ResourceAccessException.class)
    public BaseResp<?> handleResourceAccessException(ResourceAccessException e) {
        log.error(e.getMessage(), e);
        return BaseRespUtil.Error(ExceptionENU.ResourceAccessException.getCode(), ExceptionENU.ResourceAccessException.getMsg());
    }

//    @ExceptionHandler(ClientProtocolException.class)
//    public BaseResp<?> handleMyBatisSystemException(MyBatisSystemException e) {
//        log.error(e.getMessage(), e);
//        return BaseRespUtil.Error(ExceptionENU.MyBatisSystemException.getCode(), ExceptionENU.MyBatisSystemException.getMsg());
//    }

    // endregion

//    @ExceptionHandler({UnauthorizedException.class, AuthorizationException.class})
//    public Result<?> handleAuthorizationException(AuthorizationException e) {
//        log.error(e.getMessage(), e);
//        return Result.noauth("没有权限，请联系管理员授权");
//    }

//    @ExceptionHandler(Exception.class)
//    public Result<?> handleException(Exception e) {
//        log.error(e.getMessage(), e);
//        return Result.error("操作失败，" + e.getMessage());
//    }

    /**
     * @param e
     * @return
     * @Author lq
     */
//    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
//    public Result<?> HttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
//        StringBuffer sb = new StringBuffer();
//        sb.append("不支持");
//        sb.append(e.getMethod());
//        sb.append("请求方法，");
//        sb.append("支持以下");
//        String[] methods = e.getSupportedMethods();
//        if (methods != null) {
//            for (String str : methods) {
//                sb.append(str);
//                sb.append("、");
//            }
//        }
//        log.error(sb.toString(), e);
//        //return Result.error("没有权限，请联系管理员授权");
//        return Result.error(405, sb.toString());
//    }

//    /**
//     * spring默认上传大小100MB 超出大小捕获异常MaxUploadSizeExceededException
//     */
//    @ExceptionHandler(MaxUploadSizeExceededException.class)
//    public Result<?> handleMaxUploadSizeExceededException(MaxUploadSizeExceededException e) {
//        log.error(e.getMessage(), e);
//        return Result.error("文件大小超出10MB限制, 请压缩或降低文件质量! ");
//    }
//
//    @ExceptionHandler(DataIntegrityViolationException.class)
//    public Result<?> handleDataIntegrityViolationException(DataIntegrityViolationException e) {
//        log.error(e.getMessage(), e);
//        return Result.error("字段太长,超出数据库字段的长度");
//    }
//
//    @ExceptionHandler(PoolException.class)
//    public Result<?> handlePoolException(PoolException e) {
//        log.error(e.getMessage(), e);
//        return Result.error("Redis 连接异常!");
//    }

}
